package cn.js.sangu.unitStore.controller;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.hutool.core.util.StrUtil;
import cn.js.sangu.unitStore.common.LogType;
import cn.js.sangu.unitStore.common.MyLogsAOP;
import cn.js.sangu.unitStore.common.R;
import cn.js.sangu.unitStore.common.exception.ServiceException;
import cn.js.sangu.unitStore.entity.ProcessNode;
import cn.js.sangu.unitStore.entity.ProcessNodeTemplate;
import cn.js.sangu.unitStore.entity.User;
import cn.js.sangu.unitStore.service.ProcessNodeService;
import cn.js.sangu.unitStore.service.ProcessNodeTemplateService;
import cn.js.sangu.unitStore.service.UserService;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequestMapping("processNode")
@RestController
public class ProcessNodeController {

    static final String OPERATION_PROCESS_NODE = "流程节点模板";

    @Autowired
    UserService userService;

    @Autowired
    private ProcessNodeService processNodeService;

    @Autowired
    private ProcessNodeTemplateService processNodeTemplateService;

    @MyLogsAOP(operation = OPERATION_PROCESS_NODE, operaType = LogType.LOOKUP)
    @GetMapping("findByPage")
    public R findByPage(@RequestParam Integer pageNum,
            @RequestParam Integer pageSize,
            @RequestParam(required = false) String creator,
            @RequestParam(required = false) String templateName) {
        // 参数校验
        if (pageNum == null || pageNum < 1) {
            throw new ServiceException("页码必须为正整数");
        }
        if (pageSize == null || pageSize < 1 || pageSize > 100) {
            throw new ServiceException("每页数量必须在1-100之间");
        }

        QueryWrapper<ProcessNodeTemplate> wrapper = new QueryWrapper<>();
        // 字段名检查：确保实体类和数据库表字段匹配
        // 如果数据库中实际字段名不同，请修改这里
        wrapper.like(StrUtil.isNotBlank(creator), "user_id", creator);
        wrapper.like(StrUtil.isNotBlank(templateName), "template_name", templateName); // 假设数据库字段是下划线命名
        wrapper.orderByDesc("id");

        // 构建page对象
        Page<ProcessNodeTemplate> paramRes = new Page<>(pageNum, pageSize);
        try {
            paramRes = processNodeTemplateService.page(paramRes, wrapper);
        } catch (DataAccessException e) {
            log.error("数据库访问异常: {}", e.getMessage(), e);
            throw new ServiceException("数据库查询失败: " + e.getMostSpecificCause().getMessage());
        } catch (Exception e) {
            log.error("系统异常: {}", e.getMessage(), e);
            throw new ServiceException("系统接口出现错误，请联系管理员");
        }
        return R.ok(paramRes.setRecords(suppleName(paramRes.getRecords())));
    }

    /**
     * 补充创建人+修改人名称
     * 
     * @param list 流程节点模板列表
     * @return 补充后的列表
     */
    private List<ProcessNodeTemplate> suppleName(List<ProcessNodeTemplate> list) {
        if (list == null || list.isEmpty()) {
            return list;
        }

        for (ProcessNodeTemplate item : list) {
            // 防止空指针异常
            if (item == null) {
                continue;
            }

            // 创建人
            if (item.getUserId() != null) {
                User author = userService.getById(item.getUserId());
                if (author != null) {
                    item.setUsername(author.getName());
                }
            }

            // 修改人
            if (item.getModifier() != null) {
                User modifier = userService.getById(item.getModifier());
                if (modifier != null) {
                    item.setModifierName(modifier.getName());
                }
            }
        }
        return list;
    }

    @MyLogsAOP(operation = OPERATION_PROCESS_NODE, operaType = LogType.ADD)
    @PostMapping("save")
    public R save(@RequestBody ProcessNodeTemplate param) {
        try {
            // 保存模板信息
            ProcessNodeTemplate res = processNodeTemplateService.saveInfo(param);
            // 处理子节点数据
            if (param.getChildren() != null && !param.getChildren().isEmpty()) {
                for (ProcessNode node : param.getChildren()) {
                    node.setTemplateId(res.getId()); // 设置模板ID
                    processNodeService.save(node);
                }
            }
            return R.ok("《" + res.getTemplateName() + "》模板保存成功");
        } catch (ServiceException e) {
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("保存模板失败", e);
            return R.fail("保存模板失败，请联系管理员");
        }
    }

    @MyLogsAOP(operation = OPERATION_PROCESS_NODE, operaType = LogType.UPDATE)
    @PutMapping("update")
    public R update(@RequestBody ProcessNodeTemplate param) {
        try {
            // 参数校验
            if (param == null || param.getId() == null) {
                return R.fail("参数无效或模板ID不能为空");
            }

            param.setHasChildren(param.getChildren() != null && !param.getChildren().isEmpty());

            // 调用服务层更新模板
            processNodeTemplateService.updateInfo(param);

            // 先删除原有的子节点
            processNodeService.removeByTemplateId(param.getId());

            // 保存新的子节点数据
            List<ProcessNode> children = param.getChildren();
            if (children != null && !children.isEmpty()) {
                for (ProcessNode item : children) {
                    item.setTemplateId(param.getId()); // 设置模板ID
                }
                // 批量保存子节点，提高效率
                processNodeService.saveBatch(children);
            }

            log.info("更新模板成功，模板ID: {}", param.getId());
            return R.ok("修改成功");
        } catch (ServiceException e) {
            log.warn("更新模板失败: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("更新模板异常", e);
            return R.fail("更新模板失败，请联系管理员");
        }
    }

    /**
     * 根据ID获取模板
     */
    @GetMapping("/template/{id}")
    public R getTemplateById(@PathVariable Integer id) {
        try {
            ProcessNodeTemplate template = processNodeTemplateService.getById(id);
            if (template == null) {
                return R.fail("未找到该模板");
            }
            return R.ok(template);
        } catch (Exception e) {
            log.error("获取模板失败", e);
            return R.fail("获取模板失败，请联系管理员");
        }
    }

    /**
     * 删除模板
     */
    @DeleteMapping("/template/{id}")
    @MyLogsAOP(operation = OPERATION_PROCESS_NODE, operaType = LogType.DELETE)
    public R deleteTemplate(@PathVariable Integer id) {
        try {
            // 先删除关联的节点
            processNodeService.removeByTemplateId(id);
            // 再删除模板
            boolean success = processNodeTemplateService.removeById(id);
            if (success) {
                return R.ok("删除成功");
            } else {
                return R.fail("删除失败，模板不存在");
            }
        } catch (Exception e) {
            log.error("删除模板失败", e);
            return R.fail("删除模板失败，请联系管理员");
        }
    }

    /**
     * 根据模板ID获取节点列表
     */
    @GetMapping("getChildrenById")
    public R getChildrenById(@RequestParam Integer id) {
        try {
            return R.ok(processNodeService.getNodesByTemplateId(id));
        } catch (Exception e) {
            log.error("获取节点列表失败", e);
            return R.fail("获取节点列表失败，请联系管理员");
        }
    }

    /**
     * 根据ID获取节点
     */
    @GetMapping("/node/{id}")
    public R getNodeById(@PathVariable Integer id) {
        try {
            ProcessNode node = processNodeService.getById(id);
            if (node == null) {
                return R.fail("未找到该节点");
            }
            return R.ok(node);
        } catch (Exception e) {
            log.error("获取节点失败", e);
            return R.fail("获取节点失败，请联系管理员");
        }
    }

    /**
     * 添加节点
     */
    @PostMapping
    public R addNode(@RequestBody ProcessNode node) {
        try {
            boolean success = processNodeService.save(node);
            if (success) {
                return R.ok("添加成功");
            } else {
                return R.fail("添加失败");
            }
        } catch (Exception e) {
            log.error("添加节点失败", e);
            return R.fail("添加节点失败，请联系管理员");
        }
    }

    /**
     * 更新节点
     */
    @PutMapping("/{id}")
    public R updateNode(@PathVariable Integer id, @RequestBody ProcessNode node) {
        try {
            node.setId(id);
            boolean success = processNodeService.updateById(node);
            if (success) {
                return R.ok("更新成功");
            } else {
                return R.fail("更新失败，节点不存在");
            }
        } catch (Exception e) {
            log.error("更新节点失败", e);
            return R.fail("更新节点失败，请联系管理员");
        }
    }

    /**
     * 删除节点
     */
    @DeleteMapping("/node/{id}")
    public R deleteNode(@PathVariable Integer id) {
        try {
            boolean success = processNodeService.removeById(id);
            if (success) {
                return R.ok("删除成功");
            } else {
                return R.fail("删除失败，节点不存在");
            }
        } catch (Exception e) {
            log.error("删除节点失败", e);
            return R.fail("删除节点失败，请联系管理员");
        }
    }

    @GetMapping("getTemplateList")
    public R getTemplateList() {
        return R.ok(processNodeTemplateService.list());
    }

    @GetMapping("getStepsList")
    public R getStepsList(Integer templateId) {
        return R.ok(processNodeService.getNodesByTemplateId(templateId));
    }
}
